<!DOCTYPE html>
<html>
<head>
<title>List Indenting and Outdenting Tests</title>
<link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-git.css" type="text/css" />
<script src="http://code.jquery.com/qunit/qunit-git.js"></script>
<script src="qunit/connector.js"></script>
<script type="text/javascript" src="qunit/runner.js"></script>
<script type="text/javascript" src="js/utils.js"></script>
<script type="text/javascript" src="js/tiny_mce_loader.js"></script>
<script type="text/javascript" src="js/dsl/dsl.js"></script>
<script type="text/javascript" src="js/dsl/states.js"></script>
<script type="text/javascript" src="js/lists/actions.js"></script>
<script>
// Expected Results
var EmptyOL = "<ol><li></li></ol>";
var EmptyUL = "<ul><li></li></ul>";
var NonEmptyOL = "<ol><li>Test</li></ol>";
var NonEmptyUL = "<ul><li>Test</li></ul>";
var EmptyOLConvertedToP = '<ol><li>Before</li></ol><p>&nbsp;</p><ol><li>After</li></ol>';
var EmptyULConvertedToP = '<ul><li>Before</li></ul><p>&nbsp;</p><ul><li>After</li></ul>';
var NonEmptyOLConvertedToP = '<ol><li>Before</li></ol><p>Test</p><ol><li>After</li></ol>';
var NonEmptyULConvertedToP = '<ul><li>Before</li></ul><p>Test</p><ul><li>After</li></ul>';

QUnit.config.reorder = false;
QUnit.config.autostart = false;

module('Lists - Indenting', {
	autostart: false,
	setup: function() {
		window.queue = new dsl.Queue();
	}
});

// Tests
asyncTest('Collapsed Selection - Indent Actions', function() {
	Indenting.a(NonEmptyParagraph).enablesState('outdent').andGives('<p style="margin-left: 30px;">Test</p>');
	Indenting.a(NonEmptyHeading).enablesState('outdent').andGives('<h1 style="margin-left: 30px;">Test</h1>');
	Indenting.a(ParagraphWithMarginLeft).enablesState('outdent').andGives('<p style="margin-left: 90px;">Test</p>');
	Indenting.a(ParagraphWithPaddingLeft).enablesState('outdent').andGives('<p style="margin-left: 90px;">Test</p>');
	Indenting.a(ParagraphWithMarginAndPaddingLeft).enablesState('outdent').andGives('<p style="margin-left: 150px;">Test</p>');
	
	Indenting.a(EmptyOrderedListItem).enablesState('outdent').andGives('<ol><li>Before<ol><li>&nbsp;</li></ol></li><li>After</li></ol>');
	Indenting.a(EmptyUnorderedListItem).enablesState('outdent').andGives('<ul><li>Before<ul><li>&nbsp;</li></ul></li><li>After</li></ul>');
	Indenting.a(NonEmptyOrderedListItem).enablesState('outdent').andGives('<ol><li>Before<ol><li>Test</li></ol></li><li>After</li></ol>');
	Indenting.a(NonEmptyUnorderedListItem).enablesState('outdent').andGives('<ul><li>Before<ul><li>Test</li></ul></li><li>After</li></ul>');
	
	// TODO: Test invalid starting point like <ol><li>Before</li><ol><li>Indented</li></ol></ol>
	Indenting.a(NestedEmptyOrderedListItem).enablesState('outdent').andGives('<ol><li>Before<ol><li style="list-style-type: none;"><ol><li>&nbsp;</li></ol></li></ol></li><li>After</li></ol>');
	Indenting.a(NestedEmptyUnorderedListItem).enablesState('outdent').andGives('<ul><li>Before<ul><li style="list-style-type: none;"><ul><li>&nbsp;</li></ul></li></ul></li><li>After</li></ul>');
	Indenting.a(NestedNonEmptyOrderedListItem).enablesState('outdent').andGives('<ol><li>Before<ol><li style="list-style-type: none;"><ol><li>Test</li></ol></li></ol></li><li>After</li></ol>');
	Indenting.a(NestedNonEmptyUnorderedListItem).enablesState('outdent').andGives('<ul><li>Before<ul><li style="list-style-type: none;"><ul><li>Test</li></ul></li></ul></li><li>After</li></ul>');

	Indenting.a(OrderedListItemWithNestedChild).enablesState('outdent').andGives('<ol><li style="list-style-type: none;"><ol><li>Item1</li><li>Nested</li></ol></li></ol>');
	Indenting.a(UnorderedListItemWithNestedChild).enablesState('outdent').andGives('<ul><li style="list-style-type: none;"><ul><li>Item1</li><li>Nested</li></ul></li></ul>');

	Indenting.a(OrderedListWithAdjacentNestedLists).enablesState('outdent').andGives('<ol><li style="list-style-type: none;"><ol><li>Item 1</li><li>Item 2</li><li>Item 3</li></ol></li></ol>');
	Indenting.a(UnorderedListWithAdjacentNestedLists).enablesState('outdent').andGives('<ul><li style="list-style-type: none;"><ul><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul></li></ul>');

	Indenting.a(OrderedListItemWithNestedAlphaList).gives('<ol><li style="list-style-type: none;"><ol><li>Item</li></ol><ol style="list-style-type: lower-alpha;"><li>Nested</li></ol></li></ol>');

	Indenting.a(OrderedLowerAlphaListItem).enablesState('outdent').andGives('<ol style="list-style-type: lower-alpha;"><li>Item 1<ol style="list-style-type: lower-alpha;"><li>Item 2</li></ol></li></ol>');
	Indenting.a(UnorderedSquareListItem).enablesState('outdent').andGives('<ul style="list-style-type: square;"><li>Item 1<ul style="list-style-type: square;"><li>Item 2</li></ul></li></ul>');
	queue.done();
});

asyncTest('Collapsed Selection - Outdent Actions', function() {
	Outdenting.a(NonEmptyParagraph).disablesState('outdent').andGives('<p>Test</p>');
	Outdenting.a(NonEmptyHeading).disablesState('outdent').andGives('<h1>Test</h1>');
	Outdenting.a(ParagraphWithMarginLeft).enablesState('outdent').andGives('<p style="margin-left: 30px;">Test</p>');
	Outdenting.a(ParagraphWithPaddingLeft).enablesState('outdent').andGives('<p style="margin-left: 30px;">Test</p>');
	Outdenting.a(ParagraphWithMarginAndPaddingLeft).gives('<p style="margin-left: 90px;">Test</p>');

	Outdenting.a(EmptyOrderedListItem).disablesState('outdent').andGives(EmptyOLConvertedToP);
	Outdenting.a(EmptyUnorderedListItem).disablesState('outdent').andGives(EmptyULConvertedToP);
	Outdenting.a(NonEmptyOrderedListItem).disablesState('outdent').andGives(NonEmptyOLConvertedToP);
	Outdenting.a(NonEmptyUnorderedListItem).disablesState('outdent').andGives(NonEmptyULConvertedToP);
	
	Outdenting.a(NestedEmptyOrderedListItem).enablesState('outdent').andGives('<ol><li>Before</li><li>&nbsp;</li><li>After</li></ol>');
	Outdenting.a(NestedEmptyUnorderedListItem).enablesState('outdent').andGives('<ul><li>Before</li><li>&nbsp;</li><li>After</li></ul>');
	Outdenting.a(NestedNonEmptyOrderedListItem).enablesState('outdent').andGives('<ol><li>Before</li><li>Test</li><li>After</li></ol>');
	Outdenting.a(NestedNonEmptyUnorderedListItem).enablesState('outdent').andGives('<ul><li>Before</li><li>Test</li><li>After</li></ul>');

	Outdenting.a(OrderedListItemWithNestedChild).disablesState('outdent').andGives('<p>Item1</p><ol><li style="list-style-type: none;"><ol><li>Nested</li></ol></li></ol>');
	Outdenting.a(UnorderedListItemWithNestedChild).disablesState('outdent').andGives('<p>Item1</p><ul><li style="list-style-type: none;"><ul><li>Nested</li></ul></li></ul>');

	Outdenting.a(NestedOrderedListWithMultipleItems).enablesState('outdent').andGives('<ol><li>Before</li><li>Item1<ol><li>Item2</li></ol></li></ol>');
	Outdenting.a(NestedUnorderedListWithMultipleItems).enablesState('outdent').andGives('<ul><li>Before</li><li>Item1<ul><li>Item2</li></ul></li></ul>');

	Outdenting.a(OrderedListItemWithMargin).enablesState('outdent').andGives('<ol><li style="margin-left: 30px;">Test</li></ol>');
	Outdenting.a(UnorderedListItemWithMargin).enablesState('outdent').andGives('<ul><li style="margin-left: 30px;">Test</li></ul>');

	Outdenting.a(CenteredListItem).enablesState('outdent').andGives('<ul><li style="text-align: left;">Item1</li><li>Item2</li></ul>');
	Outdenting.a(ItemInCenteredList).enablesState('outdent').andGives('<ul style="text-align: center;"><li style="text-align: left;">Item1</li><li>Item2</li></ul>');
	Outdenting.a(RightAlignedListItem).enablesState('outdent').andGives('<ul><li style="text-align: left;">Item1</li><li>Item2</li></ul>');
	Outdenting.a(ItemInRightAlignedList).enablesState('outdent').andGives('<ul style="text-align: right;"><li style="text-align: left;">Item1</li><li>Item2</li></ul>');
	queue.done();
});

asyncTest('Type Tab in List', function() {
	editor.setContent('<ol><li>Test</li></ol>');
	setSelection('li', 0);
	checkIfKeystrokeFiresAction('\t', false, 'Indent', true);
});

asyncTest('Type Shift-Tab in List', function() {
	editor.setContent('<ol><li>Test</li></ol>');
	setSelection('li', 0);
	checkIfKeystrokeFiresAction('\t', true, 'Outdent', true);
});

function checkIfKeystrokeFiresAction(keystroke, shift, actionName, expected) {
	expect(1);
	var actionFired = false;
	function listener(ed, e) {
		if (e == actionName) {
			actionFired = true;
			return true;
		}
	}
	editor.onBeforeExecCommand.add(listener);
	
	fakeKeyPressAction(keystroke, shift)(function() {
		equal(actionFired, expected, actionName + ' command triggered?');
		editor.onBeforeExecCommand.remove(listener);
		QUnit.start();
	}, editor.getWin());
}

asyncTest('Expanded Selection, List Types - Indent Action', function() {
	Indenting.a(SingleLiOlSelection).enablesState('Outdent').andGives('<ol><li style="list-style-type: none;"><ol><li>Item 1</li></ol></li></ol>');
	Indenting.a(MultiLiOlSelection).enablesState('Outdent').andGives('<ol><li style="list-style-type: none;"><ol><li>Item 1</li><li>Item 2</li></ol></li></ol>');
	Indenting.a(SingleLiUlSelection).enablesState('Outdent').andGives('<ul><li style="list-style-type: none;"><ul><li>Item 1</li></ul></li></ul>');
	Indenting.a(MultiLiUlSelection).enablesState('Outdent').andGives('<ul><li style="list-style-type: none;"><ul><li>Item 1</li><li>Item 2</li></ul></li></ul>');

	Indenting.a(IndentedOlInOlCorrectSelection).enablesState('Outdent').andGives('<ol><li style="list-style-type: none;"><ol><li>Item 1<ol><li>Indented</li></ol></li></ol></li></ol>');
	Indenting.a(IndentedOlInOlIncorrectSelection).enablesState('Outdent').andGives('<ol><li style="list-style-type: none;"><ol><li>Item 1<ol><li>Indented</li></ol></li></ol></li></ol>');

	// TODO: Selection only in indented list.
	
	Indenting.a(IndentedUlInUlCorrectSelection).enablesState('Outdent').andGives('<ul><li style="list-style-type: none;"><ul><li>Item 1<ul><li>Indented</li></ul></li></ul></li></ul>');
	Indenting.a(IndentedUlInUlIncorrectSelection).enablesState('Outdent').andGives('<ul><li style="list-style-type: none;"><ul><li>Item 1<ul><li>Indented</li></ul></li></ul></li></ul>');

	Indenting.a(ParagraphBeforeOlSelection).enablesState('Outdent').andGives('<p style="margin-left: 30px;">Before</p><ol><li style="list-style-type: none;"><ol><li>Item 1</li></ol></li></ol>');
	Indenting.a(ParagraphBeforeUlSelection).enablesState('Outdent').andGives('<p style="margin-left: 30px;">Before</p><ul><li style="list-style-type: none;"><ul><li>Item 1</li></ul></li></ul>');
	
	Indenting.a(ParagraphAfterOlSelection).enablesState('Outdent').andGives('<ol><li style="list-style-type: none;"><ol><li>Item 1</li></ol></li></ol><p style="margin-left: 30px;">After</p>');
	Indenting.a(ParagraphAfterUlSelection).enablesState('Outdent').andGives('<ul><li style="list-style-type: none;"><ul><li>Item 1</li></ul></li></ul><p style="margin-left: 30px;">After</p>');

	
	Indenting.a(ParagraphBeforeAndAfterOlSelection).enablesState('Outdent').andGives('<p style="margin-left: 30px;">Before</p><ol><li style="list-style-type: none;"><ol><li>Item 1</li></ol></li></ol><p id="after" style="margin-left: 30px;">After</p>');
	Indenting.a(ParagraphBeforeAndAfterUlSelection).enablesState('Outdent').andGives('<p style="margin-left: 30px;">Before</p><ul><li style="list-style-type: none;"><ul><li>Item 1</li></ul></li></ul><p id="after" style="margin-left: 30px;">After</p>');
	queue.done();
});

asyncTest('Expanded Selection, List Types - Outdent Action', function() {
	Outdenting.a(SingleLiOlSelection).disablesState('Outdent').andGives('<p>Item 1</p>');
	Outdenting.a(MultiLiOlSelection).disablesState('Outdent').andGives('<p>Item 1</p><p>Item 2</p>');
	Outdenting.a(SingleLiUlSelection).disablesState('Outdent').andGives('<p>Item 1</p>');
	Outdenting.a(MultiLiUlSelection).disablesState('Outdent').andGives('<p>Item 1</p><p>Item 2</p>');

	Outdenting.a(IndentedOlInOlCorrectSelection).disablesState('Outdent').andGives('<p>Item 1</p><ol><li>Indented</li></ol>');
	Outdenting.a(IndentedOlInOlIncorrectSelection).disablesState('Outdent').andGives('<p>Item 1</p><ol><li>Indented</li></ol>');

	// TODO: Selection only in indented list.
	
	Outdenting.a(IndentedUlInUlCorrectSelection).disablesState('Outdent').andGives('<p>Item 1</p><ul><li>Indented</li></ul>');
	Outdenting.a(IndentedUlInUlIncorrectSelection).disablesState('Outdent').andGives('<p>Item 1</p><ul><li>Indented</li></ul>');

	Outdenting.a(MultiNestedLiOlSelection).enablesState('Outdent').andGives('<ol><li>Item 1</li><li>Item 2</li></ol>');

	Outdenting.a(ParagraphBeforeOlSelection).disablesState('Outdent').andGives('<p>Before</p><p>Item 1</p>');
	Outdenting.a(ParagraphBeforeUlSelection).disablesState('Outdent').andGives('<p>Before</p><p>Item 1</p>');
	
	Outdenting.a(ParagraphAfterOlSelection).disablesState('Outdent').andGives('<p>Item 1</p><p>After</p>');
	Outdenting.a(ParagraphAfterUlSelection).disablesState('Outdent').andGives('<p>Item 1</p><p>After</p>');

	
	Outdenting.a(ParagraphBeforeAndAfterOlSelection).disablesState('Outdent').andGives('<p>Before</p><p>Item 1</p><p id="after">After</p>');
	Outdenting.a(ParagraphBeforeAndAfterUlSelection).disablesState('Outdent').andGives('<p>Before</p><p>Item 1</p><p id="after">After</p>');
	queue.done();
});
var initTinyFunction = function(){
	tinyMCE.init({
		mode : "exact",
		elements : "elm1",
		theme : "advanced",
		cleanup: true,
		// Turn this off because we want the list actions to create the right DOM structure from the start.
		fix_list_elements: false,
		plugins : 'lists',
		add_unload_trigger : false,
		apply_source_formatting : 0,
		init_instance_callback : function(ed) {
			editor = ed;

			ed.onNodeChange.addToTop(function() {
				return false;
			});
		}
	});
};
</script>
</head>
<body>
	<h1 id="qunit-header">List Indenting and Outdenting Tests</h1>
	<h2 id="qunit-banner"></h2>
	<div id="qunit-testrunner-toolbar"></div>
	<h2 id="qunit-userAgent"></h2>
	<ol id="qunit-tests"></ol>
	<div id="content">
		<textarea id="elm1" name="elm1"></textarea>
	</div>
	<p><input type="text" id="state"><input type="button" value="Load state" onclick="loadState();"></p>
	<script type="text/javascript" language="JavaScript" src="jsrobot/robot.js"></script>
	<script>
	initWhenTinyAndRobotAreReady(initTinyFunction);

	function loadState() {
		window[document.getElementById('state').value]();
		editor.focus();
	}
	</script>
</body>
</html>
